﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using OneOfAll.Common.Models;
using OneOfAll.UserControls;
using OneOfAll.Common.Util;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.ServiceModel.Channels;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using Point = System.Windows.Point;
using System.Windows.Data;
using OneOfAll.Common.Bussiness;
using NLog.Targets;
using System.Security.Cryptography;
using OneOfAll.View;

namespace OneOfAll.ViewModel
{
    public class CityViewModel : ViewModelBase
    {
        #region 字段
        private ConstructionControl planningConstruction = null;
        private Node[,] Nodes;
        PathHelper ph;
        public ICollectionView ViewSource_Construction { get; set; }

        PeopleView peopleView = new PeopleView();
        PeopleInfoView peopleInfoView = new PeopleInfoView();

        #endregion

        #region 属性
        private double cameraX = 0.0;
        public double CameraX
        {
            get { return cameraX; }
            set { cameraX = value; RaisePropertyChanged(); }
        }

        private double cameraY = 0.0;
        public double CameraY
        {
            get { return cameraY; }
            set { cameraY = value; RaisePropertyChanged(); }
        }

        private double scalueValue = 1.0;
        public double ScalueValue
        {
            get { return scalueValue; }
            set { scalueValue = value; RaisePropertyChanged(); }
        }

        private double cityWidth = 0.0;
        public double CityWidth
        {
            get { return cityWidth; }
            set { cityWidth = value; RaisePropertyChanged(); }
        }

        private double cityHeight = 0.0;
        public double CityHeight
        {
            get { return cityHeight; }
            set { cityHeight = value; RaisePropertyChanged(); }
        }

        private ObservableCollection<UserControl> objectList = new ObservableCollection<UserControl>();
        public ObservableCollection<UserControl> ObjectList
        {
            get { return objectList; }
            set { objectList = value; RaisePropertyChanged(); }
        }

        private CityEditorStatusEnum editorStatus = CityEditorStatusEnum.查看;
        public CityEditorStatusEnum EditorStatus
        {
            get { return editorStatus; }
            set
            {
                editorStatus = value; RaisePropertyChanged();
            }
        }

        private int selectedConstructionType = 0;
        public int SelectedConstructionType
        {
            get { return selectedConstructionType; }
            set { selectedConstructionType = value; ViewSource_Construction.Refresh(); RaisePropertyChanged(); }
        }

        private ObservableCollection<ConstructionOptionControl> constructionButtonList = new ObservableCollection<ConstructionOptionControl>();
        public ObservableCollection<ConstructionOptionControl> ConstructionButtonList
        {
            get { return constructionButtonList; }
            set { constructionButtonList = value; RaisePropertyChanged(); }
        }

        private ObservableCollection<UserControl> childrenWindows = new ObservableCollection<UserControl>();
        public ObservableCollection<UserControl> ChildrenWindows
        {
            get { return childrenWindows; }
            set { childrenWindows = value; RaisePropertyChanged(); }
        }
        #endregion

        #region 命令
        private RelayCommand<string> buttonClickCmd;
        public RelayCommand<string> ButtonClickCmd
        {
            get
            {
                if (buttonClickCmd == null)
                {
                    buttonClickCmd = new RelayCommand<string>((p) => ButtonClickFunc(p));
                }
                return buttonClickCmd;
            }
        }



        private RelayCommand mouseLeftButtonDownCmd;
        public RelayCommand MouseLeftButtonDownCmd
        {
            get
            {
                if (mouseLeftButtonDownCmd == null)
                {
                    mouseLeftButtonDownCmd = new RelayCommand(() => MouseLeftButtonDownFunc());
                }
                return mouseLeftButtonDownCmd;
            }
        }

        private RelayCommand mouseRightButtonDownCmd;
        public RelayCommand MouseRightButtonDownCmd
        {
            get
            {
                if (mouseRightButtonDownCmd == null)
                {
                    mouseRightButtonDownCmd = new RelayCommand(() => MouseRightButtonDownFunc());
                }
                return mouseRightButtonDownCmd;
            }
        }


        #endregion

        #region 方法
        private void ButtonClickFunc(string p)
        {
            switch (p)
            {
                case "人物":
                    Messenger.Default.Send("PeopleView", Global.GlobalResource.ShowChildrenInfo);
                    break;
                case "拆除":
                    planningConstruction = null;
                    EditorStatus = CityEditorStatusEnum.拆除;
                    break;
                case "保存":
                    SaveArchive();
                    break;
                case "暂停":
                    Stop();
                    break;
                case "继续":
                    GoOn();
                    break;
            }
        }

        private void SaveArchive()
        {
            Stop();
            Global.GlobalResource.SaveArchive();
            GoOn();
        }

        public void Stop()
        {
            Global.GlobalResource.IsRunning = false;
            foreach (PeopleControl item in ObjectList.Where(t => t is PeopleControl))
            {
                if (item == null) continue;
                item.Stop();
            }
        }

        public void GoOn()
        {
            Global.GlobalResource.IsRunning = true;
            foreach (PeopleControl item in ObjectList.Where(t => t is PeopleControl))
            {
                if (item == null) continue;
                item.Start();
            }
        }


        private void MouseLeftButtonDownFunc()
        {
            switch (EditorStatus)
            {
                case CityEditorStatusEnum.修建:
                    ConfirmedConstruction();
                    planningConstruction = null;
                    EditorStatus = CityEditorStatusEnum.查看;
                    break;
                case CityEditorStatusEnum.拆除:
                    Dismantle();
                    break;
                case CityEditorStatusEnum.查看:
                    LookForClickHand();
                    
                    break;
            }
        }

        private void LookForClickHand()
        {
            var constructionList = ObjectList.Where(t => t is ConstructionControl).ToList();
            foreach (ConstructionControl item in constructionList)
            {
                if (item == null) continue;
                item.IsSelected = false;
            }
            var control = constructionList.FirstOrDefault(t => (t as ConstructionControl).Info.IsSelected);
            if (control != null) (control as ConstructionControl).IsSelected = true;
        }

        private void Dismantle()
        {
            var item = Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.FirstOrDefault(t => t.IsSelected);
            if (item != null)
            {
                Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.Remove(item);
                var control = ObjectList.Where(t => t is ConstructionControl).FirstOrDefault(t => (t as ConstructionControl).Info.Key == item.Key);
                if (control != null)
                {
                    ObjectList.Remove(control);
                }
                foreach (var point in item.PointList)
                {
                    Nodes[(int)point.X, (int)point.Y].isWalkable = true;
                }
                PeopleOutHand(item);
                BuildInfluenceByRemoveHand(item);
                BuildResourceByRemoveHand(item);
                RefushCityWalk();
            }
        }



        private void PeopleOutHand(ConstructionModel item)
        {
            switch (item.ConstructionType)
            {
                case ConstructionTypeEnum.居住:
                    foreach (var data in Global.GlobalResource.ArchiveInfo.PeopleList.Where(t => t.HomeKey == item.Key))
                    {
                        var people = Global.GlobalResource.ArchiveInfo.PeopleList.FirstOrDefault(t => t.Key == data.Key);
                        if (people == null) continue;
                        switch (people.Status)
                        {
                            case ObjectStatusEnum.空闲:
                            case ObjectStatusEnum.移动:
                                RemoveControl(people);
                                people.Status = ObjectStatusEnum.死亡;
                                break;
                            case ObjectStatusEnum.工作:
                                var workConstruction = Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.FirstOrDefault(t => t.Key == people.WorkKey);
                                if (workConstruction != null)
                                {
                                    var info = workConstruction.PeopleList.FirstOrDefault(t => t.Key == people.Key);
                                    if (info != null)
                                    {
                                        while (workConstruction.PeopleList.Contains(info))
                                        {
                                            workConstruction.PeopleList.Remove(info);
                                        }
                                    }
                                    while (workConstruction.Plan_PeopleList.Contains(people.Key))
                                    {
                                        workConstruction.Plan_PeopleList.Remove(people.Key);
                                    }
                                }
                                break;
                        }
                        people.HomeKey = -1;
                    }
                    break;
                case ConstructionTypeEnum.培养:
                case ConstructionTypeEnum.生产:
                    foreach (var data in item.PeopleList)
                    {
                        var people = Global.GlobalResource.ArchiveInfo.PeopleList.FirstOrDefault(t => t.Key == data.Key);
                        if (people == null) continue;
                        people.Status = ObjectStatusEnum.空闲;
                        CreatePeopleControl(people);
                    }
                    break;
            }
        }

        private void RemoveControl(PeopleModel people)
        {
            var control = ObjectList.FirstOrDefault(t => t is PeopleControl && (t as PeopleControl).Info.Key == people.Key) as PeopleControl;
            if (control != null) ControlDispose(control);
        }

        /// <summary>
        /// 确认修建
        /// </summary>
        private void ConfirmedConstruction()
        {
            if (planningConstruction == null) return;
            if (planningConstruction.Info.Limit) return;

            BuildMaterialsResourceHand(planningConstruction.Info, false);
            BuildInfluenceByAddHand(planningConstruction.Info);
            BuildResourceByAddHand(planningConstruction.Info);

            foreach (var point in planningConstruction.Info.PointList)
            {
                Nodes[(int)point.X, (int)point.Y].isWalkable = false;
            }
            Nodes[planningConstruction.Info.EntranceX, planningConstruction.Info.EntranceY].isWalkable = true;
            switch (planningConstruction.Info.ConstructionType)
            {
                case ConstructionTypeEnum.居住:
                    PeopleModel people = Global.GlobalResource.ArchiveInfo.PeopleList.FirstOrDefault(t => t.HomeKey == -1);
                    if (people == null) break;
                    people.HomeX = planningConstruction.Info.EntranceX;
                    people.HomeY = planningConstruction.Info.EntranceY;
                    people.HomeKey = planningConstruction.Info.Key;
                    people.X = people.HomeX * Global.GlobalResource.GridSize;
                    people.Y = people.HomeY * Global.GlobalResource.GridSize;
                    CreatePeopleControl(people);
                    break;
            }

            Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.Add(planningConstruction.Info);
            Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.ForEach(x => x.IsSelected = false);
            planningConstruction = null;
            RefushCityWalk();
        }

        private void BuildResourceByAddHand(ConstructionModel info)
        {
            switch (info.ConstructionType)
            {
                case ConstructionTypeEnum.生产:
                    //影响列表
                    var fluencelist = Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.Where(t => t.ConstructionType == ConstructionTypeEnum.资源 && t.ResourceInfo.Onwer == -1).
                    Where(t => t.ResourceInfo.ResourceType == info.ProductionInfo.ResourceDemand).
                    Where(t => Math.Abs(info.EntranceX - t.EntranceX) + Math.Abs(info.EntranceY - t.EntranceY) <= info.ProductionInfo.ResourceRange).ToList();
                    foreach (var item in fluencelist)
                    {
                        if (item.Key == info.Key) continue;
                        item.ResourceInfo.Onwer = info.Key;
                        info.ProductionInfo.ResourceKeyList.Add(item.Key);
                    }
                    break;
                case ConstructionTypeEnum.资源:
                    //被影响列表
                    var fluencedlist = Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.Where(t => Math.Abs(info.EntranceX - t.EntranceX) + Math.Abs(info.EntranceY - t.EntranceY) <= t.ProductionInfo.ResourceRange && 
                    t.ProductionInfo.ResourceDemandCount > t.ProductionInfo.ResourceKeyList.Count).ToList();
                    foreach (var item in fluencedlist)
                    {
                        if (item.Key == info.Key) continue;
                        if (item.ConstructionType == ConstructionTypeEnum.生产 && info.ResourceInfo.ResourceType == item.ProductionInfo.ResourceDemand)
                        {
                            info.ResourceInfo.Onwer = item.Key;
                            item.ProductionInfo.ResourceKeyList.Add(info.Key);
                            break;
                        }
                    }
                    break;
            }
        }

        private void BuildResourceByRemoveHand(ConstructionModel info)
        {
            switch (info.ConstructionType)
            {
                case ConstructionTypeEnum.生产:
                    var list = Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.Where(t => t.ConstructionType == ConstructionTypeEnum.资源).ToList(); ;
                    foreach (var item in info.ProductionInfo.ResourceKeyList)
                    {
                        var data = list.FirstOrDefault(t => t.Key == item);
                        if (data != null) data.ResourceInfo.Onwer = -1;
                    }
                    break;
                case ConstructionTypeEnum.资源:
                    //被影响列表
                    var fluencedlist = Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.Where(t => t.ResourceInfo.Onwer == info.Key &&
                    Math.Abs(info.EntranceX - t.EntranceX) + Math.Abs(info.EntranceY - t.EntranceY) <= t.ProductionInfo.ResourceRange).ToList();
                    foreach (var item in fluencedlist)
                    {
                        if (item.Key == info.Key) continue;
                        if (item.ConstructionType == ConstructionTypeEnum.生产 && item.ProductionInfo.ResourceKeyList.Contains(info.Key))
                        {
                            item.ProductionInfo.ResourceKeyList.Remove(info.Key);
                        }
                    }
                    break;
            }
            //影响列表
            var fluencelist = Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.Where(t => Math.Abs(info.EntranceX - t.EntranceX) + Math.Abs(info.EntranceY - t.EntranceY) <= info.Influence_Range).ToList();
            foreach (var item in fluencelist)
            {
                if (item.Key == info.Key) continue;
                info.InfluenceList.Add(item.GetConstructionInfluence());
            }

            
        }


        private void BuildInfluenceByAddHand(ConstructionModel info)
        {
            //影响列表
            var fluencelist = Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.Where(t => Math.Abs(info.EntranceX - t.EntranceX) + Math.Abs(info.EntranceY - t.EntranceY) <= info.Influence_Range).ToList();
            foreach (var item in fluencelist)
            {
                if (item.Key == info.Key) continue;
                info.InfluenceList.Add(item.GetConstructionInfluence());
            }
            //被影响列表
            var fluencedlist = Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.Where(t => Math.Abs(info.EntranceX - t.EntranceX) + Math.Abs(info.EntranceY - t.EntranceY) <= t.Influence_Range).ToList();
            foreach (var item in fluencedlist)
            {
                if (item.Key == info.Key) continue;
                item.InfluenceList.Add(info.GetConstructionInfluence());
            }
        }

        private void BuildInfluenceByRemoveHand(ConstructionModel info)
        {
            foreach (var item in Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList)
            {
                var data = item.InfluenceList.FirstOrDefault(t => t.Key == info.Key);
                if (data != null)
                    item.InfluenceList.Remove(data);
            }
        }


        private void BuildMaterialsResourceHand(ConstructionModel info, bool flag = true)
        {
            DataCenterManager.Instance.MaterialsResourceRemove(Global.GlobalResource.ArchiveInfo.MaterialsResource, info.MaterialsResource, 1);
            RefushConstructionLimit(flag);
        }

        private void RefushCityWalk()
        {
            foreach (var people in Global.GlobalResource.ArchiveInfo.PeopleList.Where(t => t.HomeKey != -1))
            {
                RefushCityWalk(people);
            }
        }

        private void RefushCityWalk(PeopleModel people)
        {
            ph = new PathHelper(Nodes);
            people.CityWalkPathList.Clear();
            foreach (var construction in Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList)
            {
                if (construction.ConstructionType == ConstructionTypeEnum.居住 || construction.ConstructionType == ConstructionTypeEnum.资源) continue;
                if (construction.ConstructionType == ConstructionTypeEnum.培养 && !people.Enabled_Train)
                    continue;
                if (construction.ConstructionType == ConstructionTypeEnum.生产 && !people.Enabled_Production)
                    continue;
                if (construction.ConstructionType == ConstructionTypeEnum.制作 && !people.Enabled_Make)
                    continue;
                if (Math.Abs(people.HomeX - construction.EntranceX) + Math.Abs(people.HomeY - construction.EntranceY) > people.CityWalkRange)
                    continue;
                List<Point> path = GetPath(people.HomeX, people.HomeY, construction.EntranceX, construction.EntranceY, people.CityWalkRange);
                if (path == null || path.Count == 0) continue;
                people.CityWalkPathList.Add(new ConstructionPathModel()
                {
                    Key = construction.Key,
                    Name = construction.Name,
                    Path = path
                });
            }
        }

        private List<Point> GetPath(int srcX, int srcY, int desX, int desY, int maxStep = 0)
        {
            List<Point> path = new List<Point>();
            var myResult = ph.FindPath(new Node(srcX, srcY, true),
                new Node(desX, desY, true), maxStep);
            if (myResult != null)
            {
                for (int i = 0; i < myResult.Count; i++)
                {
                    path.Add(new Point(myResult[i].x * Global.GlobalResource.GridSize, myResult[i].y * Global.GlobalResource.GridSize));
                }
            }
            return path;
        }

        private void MouseRightButtonDownFunc()
        {
            switch (EditorStatus)
            {
                case CityEditorStatusEnum.修建:
                    if (planningConstruction == null) return;
                    ObjectList.Remove(planningConstruction);
                    break;
                case CityEditorStatusEnum.移动:
                    if (planningConstruction == null) return;
                    ObjectList.Remove(planningConstruction);
                    break;
            }
            EditorStatus = CityEditorStatusEnum.查看;
        }

        private void CameraMove(Key key)
        {
            switch (key)
            {
                case Key.Up:
                case Key.W:
                    if (planningConstruction != null)
                        planningConstruction.Info.Angle = 180;
                    else
                    CameraY += 10;
                    break;
                case Key.Down:
                case Key.S:
                    if (planningConstruction != null)
                        planningConstruction.Info.Angle = 0;
                    else
                        CameraY -= 10;
                    break;
                case Key.Left:
                case Key.A:
                    if (planningConstruction != null)
                        planningConstruction.Info.Angle = 90;
                    else
                        CameraX += 10;
                    break;
                case Key.Right:
                case Key.D:
                    if (planningConstruction != null)
                        planningConstruction.Info.Angle = 270;
                    else
                        CameraX -= 10;
                    break;

            }
        }

        private void MouseMove(Point point)
        {
            switch (EditorStatus)
            {
                case CityEditorStatusEnum.修建:
                    MouseMove_Construction(point);
                    break;
                case CityEditorStatusEnum.查看:
                case CityEditorStatusEnum.拆除:
                    MouseMove_LookForOrDismantle(point);
                    break;
            }
        }

        private void MouseMove_LookForOrDismantle(Point point)
        {
            foreach (var item in Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList)
            {
                item.IsSelected = false;
            }
            foreach (var construction in Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList)
            {
                if (construction.PointList.Count(t => t.X == point.X && t.Y == point.Y) > 0)
                {
                    construction.IsSelected = true;
                    break;
                }
            }
        }

        private ConstructionControl CreateConstructionControl(ConstructionModel info)
        {
            ConstructionControl control = new ConstructionControl()
            {
                Info = info
            };
            return control;
        }

        private void MouseMove_Construction(Point point)
        {
            if (planningConstruction == null)
            {
                planningConstruction = CreateConstructionControl(new ConstructionModel() { Width = 50, Height = 30 } );
                ObjectList.Add(planningConstruction);
            }
            if (!ObjectList.Contains(planningConstruction))
                ObjectList.Add(planningConstruction);
            planningConstruction.Info.X = point.X;
            planningConstruction.Info.Y = point.Y;
            Canvas.SetLeft(planningConstruction, point.X * Global.GlobalResource.GridSize);
            Canvas.SetTop(planningConstruction, point.Y * Global.GlobalResource.GridSize);
            planningConstruction.Info.RefushPoints();
            planningConstruction.Info.Limit = false;
            foreach (var item in planningConstruction.Info.PointList)
            {
                if (item.X >= Nodes.GetLength(0) || item.Y >= Nodes.GetLength(1))
                {
                    planningConstruction.Info.Limit = true;
                    break;
                }
                if (item.X == planningConstruction.Info.EntranceX && item.Y == planningConstruction.Info.EntranceY) continue;
                if (!Nodes[(int)item.X, (int)item.Y].isWalkable)
                {
                    planningConstruction.Info.Limit = true;
                    break;
                }
            }
            Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.ForEach(x => x.IsSelected = false);
            Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.Where(t => t.ConstructionType != ConstructionTypeEnum.资源).
                Where(t => Math.Abs(planningConstruction.Info.EntranceX - t.EntranceX) + 
            Math.Abs(planningConstruction.Info.EntranceY - t.EntranceY) <= planningConstruction.Info.Influence_Range).ToList().ForEach(x =>x.IsSelected = true);
            Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.Where(t => t.ConstructionType == ConstructionTypeEnum.资源).
                Where(t => Math.Abs(planningConstruction.Info.EntranceX - t.EntranceX) +
            Math.Abs(planningConstruction.Info.EntranceY - t.EntranceY) <= t.ProductionInfo.ResourceRange).ToList().ForEach(x => x.IsSelected = true);

        }

        private void ArchiveChanged(ArchiveModel info)
        {
            if (info == null) return;
            CityWidth = info.CityInfo.Width * Global.GlobalResource.GridSize;
            CityHeight = info.CityInfo.Height * Global.GlobalResource.GridSize;
            RefushNodes(info.CityInfo);
            RefushConstruction(info.CityInfo);
            RefushPeople(info.PeopleList);
            RefushResource(info.CityInfo.AvailableConstructionList);
        }

        private void RefushResource(ObservableCollection<ConstructionModel> availableConstructionList)
        {
            ConstructionButtonList.Clear();
            foreach (var item in availableConstructionList)
            {
                ConstructionOptionControl control = new ConstructionOptionControl() { Info = item };
                control.MouseLeftButtonDown += Control_MouseLeftButtonDown;
                ConstructionButtonList.Add(control);        
            }
            ViewSource_Construction.Refresh();
            RefushConstructionLimit();
        }

        private void RefushConstructionLimit(bool flag = true)
        {
            foreach (var item in Global.GlobalResource.ArchiveInfo.CityInfo.AvailableConstructionList)
            {
                if (DataCenterManager.Instance.MaterialsResourceCheck(Global.GlobalResource.ArchiveInfo.MaterialsResource, item.MaterialsResource, 1))
                {
                    item.Limit = false;
                }
                else
                {
                    item.Limit = true;
                }
                if (flag && planningConstruction != null && planningConstruction.Info.ResourceKey == item.ResourceKey)
                    planningConstruction.Info.Limit = item.Limit;
            }
        }

        private void Control_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            ConstructionOptionControl control = sender as ConstructionOptionControl;
            if (control == null) return;
            if (control.Info.Limit) return;
            if (planningConstruction != null)
                ObjectList.Remove(planningConstruction);
            EditorStatus = CityEditorStatusEnum.修建;
            var newInfo = CloneHelper<ConstructionModel, ConstructionModel>.CloneByJson(control.Info);
            newInfo.Key = Guid.NewGuid().GetHashCode();
            planningConstruction = new ConstructionControl() { Info = newInfo };
        }

        private void RefushPeople(ObservableCollection<PeopleModel> peopleList)
        {
            foreach (var item in peopleList.Where(t => t.Status != ObjectStatusEnum.工作 && t.Status != ObjectStatusEnum.休息 && t.HomeKey != -1))
            {
                CreatePeopleControl(item);
            }
        }

        private void RefushNodes(CityInfoModel cityInfo)
        {
            Nodes = new Node[cityInfo.Width, cityInfo.Height];
            for (int x = 0; x <= Nodes.GetUpperBound(0); x++)
            {
                for (int y = 0; y <= Nodes.GetUpperBound(1); y++)
                {
                    Nodes[x, y] = new Node(x, y, true);
                }
            }

        }

        private void RefushConstruction(CityInfoModel cityInfo)
        {
            foreach (var item in cityInfo.ConstructionList)
            {
                foreach (var point in item.PointList)
                {
                    Nodes[(int)point.X, (int)point.Y].isWalkable = false;
                }
                Nodes[item.EntranceX, item.EntranceY].isWalkable = true;
                ConstructionControl control = CreateConstructionControl(item);
                ObjectList.Add(control);
                Canvas.SetLeft(control, item.X * Global.GlobalResource.GridSize);
                Canvas.SetTop(control, item.Y * Global.GlobalResource.GridSize);
            }
        }

        private void CreateCityEngine()
        {
            DispatcherTimer engineTimer = new DispatcherTimer() { Interval = new TimeSpan(0, 0, 0, 0, Global.GlobalResource.GameSpeed) };
            engineTimer.Tick += EngineTimer_Tick;
            engineTimer.Start();
        }

        private void EngineTimer_Tick(object sender, EventArgs e)
        {
            try
            {
                if (!Global.GlobalResource.IsRunning) return;
                int lastYear = Global.GlobalResource.ArchiveInfo.GameTime.Year;
                int lastMonth = Global.GlobalResource.ArchiveInfo.GameTime.Month;
                int lastDay = Global.GlobalResource.ArchiveInfo.GameTime.Day;
                int lastHour = Global.GlobalResource.ArchiveInfo.GameTime.Hour;
                Global.GlobalResource.ArchiveInfo.GameTime = Global.GlobalResource.ArchiveInfo.GameTime.AddMinutes(1);
                ConstructionHand();

                if (lastYear != Global.GlobalResource.ArchiveInfo.GameTime.Year)
                    YearChangedHand();
                if (lastMonth != Global.GlobalResource.ArchiveInfo.GameTime.Month)
                    MonthChangedHand();
                if (lastDay != Global.GlobalResource.ArchiveInfo.GameTime.Day)
                    DayChangedHand();
                if (lastHour != Global.GlobalResource.ArchiveInfo.GameTime.Hour)
                    HourChangedHand();
            }
            catch (Exception ex)
            {
                LogHelper.Instance.GetLog(LogTypeEnum.Error, "城镇引擎异常", ex);
            }
        }

        private void YearChangedHand()
        {

        }

        private void MonthChangedHand()
        {

        }

        private void DayChangedHand()
        {
            DurabilityHand();
            ProductionHand();
            TaxesHand();
        }



        private void HourChangedHand()
        {
            PeopleRestHand();
        }

        private void TaxesHand()
        {
            foreach (var item in Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.Where(t => t.ConstructionType == ConstructionTypeEnum.居住))
            {
                foreach (var data in item.LiveInfo.ConsumablesInfo.ConsumableList)
                {
                    var temp = Global.GlobalResource.ArchiveInfo.ConsumablesInfo.ConsumableList.FirstOrDefault(t => t.Type == data.Type);
                    if (temp == null)
                    {
                        data.Status = ConsumablesStatusEnum.缺失;
                        continue;
                    }
                    if (temp.Num >= data.Num)
                    {
                        data.Status = ConsumablesStatusEnum.满足;
                        temp.Num -= data.Num;
                    }
                    else
                        data.Status = ConsumablesStatusEnum.缺失;
                }
                double num = 50;
                if (item.LiveInfo.ConsumablesInfo.ConsumableList.Count > 0)
                {
                    num += 50 * (item.LiveInfo.ConsumablesInfo.ConsumableList.Count(t => t.Status == ConsumablesStatusEnum.满足) / item.LiveInfo.ConsumablesInfo.ConsumableList.Count());
                }
                else
                    num = 100;
                Global.GlobalResource.ArchiveInfo.MaterialsResource.Money += (int)(item.LiveInfo.Taxes * num / 100);
            }
        }

        private void DurabilityHand()
        {
            foreach (var item in Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.Where(t => t.ConstructionType != ConstructionTypeEnum.资源))
            {
                item.Durability -= 10;
                if (item.IsMaintain)
                {
                    int num = (100 - item.Durability) / 10;
                    if (num <= 0) continue;
                    if (DataCenterManager.Instance.MaterialsResourceCheck(Global.GlobalResource.ArchiveInfo.MaterialsResource, item.MaterialsResource, (double)num / 10.0))
                    {
                        DataCenterManager.Instance.MaterialsResourceRemove(Global.GlobalResource.ArchiveInfo.MaterialsResource, item.MaterialsResource, (double)num / 10.0);
                        item.Durability += 10 * num;
                    }
                }
            }
        }

        private void ProductionHand()
        {
            foreach (var item in Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.Where(t => t.ConstructionType == ConstructionTypeEnum.生产))
            {
                switch (item.ProductionInfo.ProductionType)
                {
                    case MaterialsTypeEnum.金钱:
                        Global.GlobalResource.ArchiveInfo.MaterialsResource.Money += item.ProductionInfo.ForecastYield;
                        break;
                    case MaterialsTypeEnum.粮草:
                        Global.GlobalResource.ArchiveInfo.MaterialsResource.Food += item.ProductionInfo.ForecastYield;
                        break;
                    case MaterialsTypeEnum.木材:
                        Global.GlobalResource.ArchiveInfo.MaterialsResource.Wood += item.ProductionInfo.ForecastYield;
                        break;
                    case MaterialsTypeEnum.石材:
                        Global.GlobalResource.ArchiveInfo.MaterialsResource.Stone += item.ProductionInfo.ForecastYield;
                        break;
                    case MaterialsTypeEnum.铁:
                        Global.GlobalResource.ArchiveInfo.MaterialsResource.Iron += item.ProductionInfo.ForecastYield;
                        break;
                    case MaterialsTypeEnum.铜:
                        Global.GlobalResource.ArchiveInfo.MaterialsResource.Copper += item.ProductionInfo.ForecastYield;
                        break;
                    case MaterialsTypeEnum.布:
                        Global.GlobalResource.ArchiveInfo.MaterialsResource.Cloth += item.ProductionInfo.ForecastYield;
                        break;
                    case MaterialsTypeEnum.丝绸:
                        Global.GlobalResource.ArchiveInfo.MaterialsResource.Silk += item.ProductionInfo.ForecastYield;
                        break;
                    case MaterialsTypeEnum.宝石:
                        Global.GlobalResource.ArchiveInfo.MaterialsResource.Gem += item.ProductionInfo.ForecastYield;
                        break;
                }
                item.ProductionInfo.CurrentEffect = 0;
            }
            RefushConstructionLimit();
        }



        private void PeopleRestHand()
        {
            foreach (var item in Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.Where(t => t.ConstructionType == ConstructionTypeEnum.居住))
            {
                List<PeopleWorkInfoModel> completeList = new List<PeopleWorkInfoModel>();
                foreach (var people in item.PeopleList)
                {
                    people.Schedule += people.WorkSpeed * item.DurablityEffect;
                    if (people.Schedule >= people.MaxValue)
                    {
                        completeList.Add(people);
                    }
                }
                foreach (var data in completeList)
                {
                    item.PeopleList.Remove(data);
                    var people = Global.GlobalResource.ArchiveInfo.PeopleList.FirstOrDefault(t => t.Key == data.Key);
                    if (people != null)
                    {
                        people.TargetKey = -1;
                        people.Vitality = people.MaxVitality;
                        people.Status = ObjectStatusEnum.空闲;
                        CreatePeopleControl(people);
                    }
                }
            }
        }

        private void ConstructionHand()
        {
            foreach (var construction in Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList)
            {
                if (construction.PeopleList.Count <= 0) continue;
                switch (construction.ConstructionType)
                {
                    case ConstructionTypeEnum.居住:
                        break;
                    case ConstructionTypeEnum.培养:
                    case ConstructionTypeEnum.生产:
                    case ConstructionTypeEnum.制作:
                        PeopleWorkHand(construction);
                        break;
                }
            }
        }

        private void PeopleWorkHand(ConstructionModel construction)
        {
            List<PeopleWorkInfoModel> completeList = new List<PeopleWorkInfoModel>();
            foreach (var item in construction.PeopleList)
            {
                item.Schedule += item.WorkSpeed;
                if (item.Schedule > item.MaxValue)
                    completeList.Add(item);
            }
            foreach (var item in completeList)
            {
                while (construction.Plan_PeopleList.Contains(item.Key))
                {
                    construction.Plan_PeopleList.Remove(item.Key);
                }
                while (construction.PeopleList.Contains(item))
                {
                    construction.PeopleList.Remove(item);
                }
                var people = Global.GlobalResource.ArchiveInfo.PeopleList.FirstOrDefault(t => t.Key == item.Key);
                if (people != null)
                {
                    DataCenterManager.Instance.WorkEffectCompleteHand(construction, people);
                    CreatePeopleControl(people);
                }
            }
            RefushConstructionLimit();
        }

        private void CreatePeopleControl(PeopleModel people)
        {
            PeopleControl control = new PeopleControl() { Info = people };
            control.Info.PropertyChanged += PeopleInfo_PropertyChanged;
            ObjectList.Add(control);
            Canvas.SetLeft(control, control.Info.X);
            Canvas.SetTop(control, control.Info.Y);
            control.Start();
        }


        private void PeopleInfo_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            BaseObjectModel data = sender as BaseObjectModel;
            PeopleControl control = ObjectList.Where(t => t is PeopleControl).FirstOrDefault(t => (t as PeopleControl).Info.Key == data.Key) as PeopleControl;
            if (control == null) return;
            switch (e.PropertyName)
            {
                case "X":
                    Canvas.SetLeft(control, data.X);
                    break;
                case "Y":
                    Canvas.SetTop(control, data.Y);
                    break;
                case "IsDispose":
                    if (control.Info.IsDispose)
                        ControlDispose(control);
                    break;
            }
        }

        private void ControlDispose(PeopleControl control)
        {
            control.Info.PropertyChanged -= PeopleInfo_PropertyChanged;
            ObjectList.Remove(control);
        }

        public List<Point> GetWorkPath(PeopleModel info)
        {
            Random rd = new Random(Guid.NewGuid().GetHashCode());

            var fullList = Global.GlobalResource.ArchiveInfo.CityInfo.GetFullConstruction();
            var enabledList = info.CityWalkPathList.Where(t => !fullList.Contains(t.Key)).ToList();
            if (enabledList.Count <= 0) return null;
            var temp = enabledList[rd.Next(enabledList.Count)];
            var target = Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.FirstOrDefault(t => t.Key == temp.Key);
            if (target == null) return null;
            info.TargetKey = target.Key;
            if (!target.Plan_PeopleList.Contains(temp.Key))
                target.Plan_PeopleList.Add(info.Key);
            ph = new PathHelper(Nodes);
            return GetPath((int)info.X / Global.GlobalResource.GridSize, (int)info.Y / Global.GlobalResource.GridSize, target.EntranceX, target.EntranceY);
        }

        public List<Point> GetBackPath(PeopleModel info)
        {
            return GetPath((int)info.X / Global.GlobalResource.GridSize, (int)info.Y / Global.GlobalResource.GridSize, info.HomeX, info.HomeY);
        }
         

        internal List<Point> GetWorkPath(PeopleModel info, int targetKey)
        {
            var target = Global.GlobalResource.ArchiveInfo.CityInfo.ConstructionList.FirstOrDefault(t => t.Key == targetKey);
            ph = new PathHelper(Nodes);
            return GetPath((int)info.X / Global.GlobalResource.GridSize, (int)info.Y / Global.GlobalResource.GridSize, target.EntranceX, target.EntranceY);
        }

        private void CloseChildrenWindow(string info)
        {
            switch (info)
            {
                case "PeopleView":
                    ChildrenWindows.Remove(peopleView);
                    break;
                case "PeopleInfoView":
                    ChildrenWindows.Remove(peopleInfoView);
                    break;
            }
        }

        private void ShowChildrenInfo(string info)
        {
            switch (info)
            {
                case "PeopleView":
                    ChildrenWindows.Remove(peopleView);
                    ChildrenWindows.Add(peopleView);
                    break;
                case "PeopleInfoView":
                    ChildrenWindows.Remove(peopleInfoView);
                    ChildrenWindows.Add(peopleInfoView);
                    break;
            }
        }


        private void RegisterMessages()
        {
            Messenger.Default.Register<Key>(this, Global.GlobalResource.CameraMove_City, new Action<Key>(key =>
            {
                CameraMove(key);
            }));
            Messenger.Default.Register<Point>(this, Global.GlobalResource.MouseMove_City, new Action<Point>(point =>
            {
                MouseMove(point);
            }));
            Messenger.Default.Register<ArchiveModel>(this, Global.GlobalResource.ArchiveChanged, new Action<ArchiveModel>(info =>
            {
                ArchiveChanged(info);
            }));
            Messenger.Default.Register<PeopleModel>(this, Global.GlobalResource.CityWalkParamsChanged, new Action<PeopleModel>(info =>
            {
                RefushCityWalk(info);
            }));
            Messenger.Default.Register<string>(this, Global.GlobalResource.CloseChildrenWindow, new Action<string>(info =>
            {
                CloseChildrenWindow(info);
            }));
            Messenger.Default.Register<string>(this, Global.GlobalResource.ShowChildrenInfo, new Action<string>(info =>
            {
                ShowChildrenInfo(info);
            }));
        }



        private void InitViewSource()
        {
            ViewSource_Construction = CollectionViewSource.GetDefaultView(ConstructionButtonList);
            ViewSource_Construction.Filter = new Predicate<object>(OnFilterMovie_Construction);
        }

        private bool OnFilterMovie_Construction(object obj)
        {
            if (ConstructionButtonList.Count == 0) return false;
            ConstructionOptionControl control = obj as ConstructionOptionControl;
            if (control == null) return false;
            return (int)control.Info.ConstructionType == SelectedConstructionType;
        }



        #endregion


        public CityViewModel()
        {
            RegisterMessages();
            InitViewSource();
            CreateCityEngine();
        }


    }
}
